package com.inspur.security.cbb3.kms.keymanager.secrets.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.security.cbb3.kms.enums.*;
import com.inspur.security.cbb3.kms.exception.UserInfoInVaildException;
import com.inspur.security.cbb3.kms.keks.service.KeksService;
import com.inspur.security.cbb3.kms.keks.vo.CipherTextVo;
import com.inspur.security.cbb3.kms.keymanager.containers.po.ContainersBean;
import com.inspur.security.cbb3.kms.keymanager.containers.service.ContainersService;
import com.inspur.security.cbb3.kms.keymanager.containersecret.service.ContainerSecretService;
import com.inspur.security.cbb3.kms.keymanager.keyorders.po.KeyOrdersBean;
import com.inspur.security.cbb3.kms.keymanager.keyorders.repository.KeyOrdersRepository;
import com.inspur.security.cbb3.kms.keymanager.keyorders.vo.KeyOrdersAddVO;
import com.inspur.security.cbb3.kms.keymanager.secrets.po.SecretsBean;
import com.inspur.security.cbb3.kms.keymanager.secrets.repository.SecretsRepository;
import com.inspur.security.cbb3.kms.keymanager.secrets.service.SecretsService;
import com.inspur.security.cbb3.kms.keymanager.secrets.vo.*;
import com.inspur.security.cbb3.kms.keymanager.secretsstore.po.SecretsStoreBean;
import com.inspur.security.cbb3.kms.keymanager.secretsstore.repository.SecretsStoreRepository;
import com.inspur.security.cbb3.kms.keymanager.secretsstore.service.SecretsStoreService;
import com.inspur.security.cbb3.kms.sysuser.po.SysUserBean;
import com.inspur.security.cbb3.kms.sysuser.service.SysUserService;
import com.inspur.security.cbb3.kms.utils.DateUtil;
import com.inspur.security.cbb3.kms.utils.KeyUtil;
import com.inspur.security.cbb3.kms.utils.PageRequestDate;
import com.inspur.security.cbb3.kms.utils.RegExpUtil;
import com.inspur.security.cbb3.kms.utils.parameter.keygen.impl.*;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.MissingServletRequestParameterException;

import javax.persistence.criteria.Predicate;
import javax.validation.ValidationException;
import java.io.IOException;
import java.util.*;

/**
 * @author: lijunchang
 * @Description: 密钥管理service实现
 * @Date: 2020/10/19
 */
@Service
@Slf4j
@Transactional(readOnly = true)
public class SecretsServiceImpl implements SecretsService {

    @Autowired
    private KeyOrdersRepository keyOrdersRepository;
    @Autowired
    private KeksService keksService;
    @Autowired
    private ContainersService containersService;
    @Autowired
    private ContainerSecretService containerSecretService;
    @Autowired
    private SecretsRepository secretsRepository;
    @Autowired
    private SecretsStoreService secretsStoreService;
    @Autowired
    private SecretsStoreRepository secretsStoreRepository;
    @Autowired
    private SysUserService sysUserService;

    /**
     * 根据密钥订单主键生成密钥
     *
     * @param keyOrderUuid 密钥订单主键
     * @return 密钥组合对象
     */
    @Override
    public AbstractSecretVO generateKey(String keyOrderUuid) {
        if (StringUtils.isBlank(keyOrderUuid)) {
            log.error("generateKey传入uuid为空");
            return null;
        }
        Optional<KeyOrdersBean> optional = keyOrdersRepository.findById(keyOrderUuid);
        if (!optional.isPresent()) {
            log.error("generateKey密钥订单对象不存在,uuid:[{}]", keyOrderUuid);
            return null;
        }
        KeyOrdersBean keyOrdersBean = optional.get();
        if (!KeyOrderStatus.Pending.name().equalsIgnoreCase(keyOrdersBean.getStatus())) {
            log.error("generateKey 密钥订单状态不正确，订单主键[{}]，订单状态[{}]", keyOrderUuid, keyOrdersBean.getStatus());
            return null;
        }
        //默认设置为失败，无需重复设置
        keyOrdersBean.setStatus(KeyOrderStatus.Failed.name());

        if (StringUtils.isBlank(keyOrdersBean.getType())) {
            log.error("generateKey 密钥订单密钥类型为空，订单主键[{}]", keyOrderUuid);
            keyOrdersBean.setErrorReason("密钥订单密钥类型为空");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        AbstractSecretVO secretVO;
        //根据订单类型进行处理
        switch (SecretKeyType.getByType(keyOrdersBean.getType())) {
            case Symmetric:
//                对称密钥
//                进行密钥生成
//                进行密钥订单更新
                secretVO = doSymmetricOrder(keyOrdersBean);
                break;
            case Asymmetric:
//                非对称密钥
//                进行容器、密钥、容器-密钥关系生成
//                进行密钥订单更新
                secretVO = doAsymmetricOrder(keyOrdersBean);
                break;
            default:
                log.error("密钥订单密钥类型不正确,uuid:[{}],type:[{}]", keyOrderUuid, keyOrdersBean.getType());
                keyOrdersBean.setErrorReason("密钥订单密钥类型不正确");
                keyOrdersRepository.save(keyOrdersBean);
                return null;
        }
        return secretVO;

    }

    @Override
    public KeyContentVO getKeyContentNoAuth(String secretsUuid) {
        KeyContentVO keyContentVO = new KeyContentVO();
        if (StringUtils.isEmpty(secretsUuid)) {
            log.error("secretsUuid is null");
            throw new ValidationException("密钥uuid为空");
        }
        //获取密钥密文
        SecretsStoreBean secretsStoreBean = secretsStoreRepository.findBySecretId(secretsUuid);
        if (secretsStoreBean == null) {
            log.error("secret key not exist");
            return null;
        }
        //解密密钥密文
        Optional<SecretsBean> secretsBeanOptional = secretsRepository.findById(secretsUuid);
        if (!secretsBeanOptional.isPresent()) {
            log.error("secret key not exist");
            return null;
        }
        SecretsBean secretsBean = secretsBeanOptional.get();
        String keyContentPlain = keksService.getDecryptString(secretsStoreBean.getCypherText(), secretsBean.getKekId());
        keyContentVO.setKeyContent(keyContentPlain);
        if (StringUtils.isNotEmpty(secretsBean.getPassword())){
            String keyPassword = keksService.getDecryptString(secretsBean.getPassword(),secretsBean.getKekId());
            keyContentVO.setKeyPassword(keyPassword);
        }
        return keyContentVO;
    }


    /**
     * 进行对称密钥业务
     *
     * @param keyOrdersBean 密钥订单
     */
    private SymmetricSecretVO doSymmetricOrder(KeyOrdersBean keyOrdersBean) {
        log.info("doSymmetricOrder,{}", keyOrdersBean);
//                对称密钥
//                进行密钥生成
//                进行密钥订单更新
        //进行参数校验,在进行订单保存时已经校验了，因此此处无需进行校验
        ObjectMapper objectMapper = new ObjectMapper();
        KeyOrdersAddVO keyOrdersAddVO;
        try {
            keyOrdersAddVO = objectMapper.readValue(keyOrdersBean.getMeta(), KeyOrdersAddVO.class);
        } catch (IOException e) {
            log.error("doSymmetricOrder 转换数据错误");
//            throw new ValidationException("对称密钥新增转换数据错误");
            keyOrdersBean.setErrorReason("对称密钥新增转换数据错误");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        //进行参数赋值
        //进行数据库新增及调用软硬件进行密钥生成
        //1.生成三级密钥
        String workKeyPlaintext = this.getSymmetricPlaintext(keyOrdersAddVO);
        if (StringUtils.isBlank(workKeyPlaintext)) {
            log.error("doSymmetricOrder 创建密钥失败 ");
            keyOrdersBean.setErrorReason("创建密钥失败");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }

        //2用二级密钥加密生成的明文密钥
        CipherTextVo cipherTextVo = keksService.getEncryptString(workKeyPlaintext, keyOrdersBean.getCreatorId());
        if (cipherTextVo == null) {
            log.error("doSymmetricOrder 密钥信息加密失败 ");
            keyOrdersBean.setErrorReason("密钥信息加密失败");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        //3进行信息存储
        //3.1将密钥表进行存储，
        SecretsBean secretsBean = this.saveSecretsBean(keyOrdersAddVO, cipherTextVo.getKekId(), null, null, keyOrdersBean.getCreatorId());
        //3.2将加密内容存储至密钥存储表
        secretsStoreService.saveSecretsStoreBean(secretsBean, cipherTextVo.getCipherText());
        //3.3进行密钥订单的更新
        keyOrdersBean.setSecretId(secretsBean.getUuid());
        keyOrdersBean.setStatus(KeyOrderStatus.Success.name());
        keyOrdersBean.setUpdatedTime(secretsBean.getCreatedTime());
        keyOrdersRepository.save(keyOrdersBean);

        SymmetricSecretVO secretVO = new SymmetricSecretVO();
        secretVO.setSecretsBean(secretsBean);

        return secretVO;
    }

    /**
     * 根据订单数据获取密钥明文
     *
     * @param keyOrdersAddVO 订单数据
     * @return 密钥明文
     */
    private String getSymmetricPlaintext(KeyOrdersAddVO keyOrdersAddVO) {
        //输出格式，是base64还是hex
        boolean isBase64 = DataOutputType.getByType(keyOrdersAddVO.getOutputFormat()).equals(DataOutputType.Base64);
        //如果有password，则需要进行解密再使用
        String password = null;
        if (StringUtils.isNotBlank(keyOrdersAddVO.getPassword()) && StringUtils.isNotBlank(keyOrdersAddVO.getKekId())) {
            password = keksService.getDecryptString(keyOrdersAddVO.getPassword(), keyOrdersAddVO.getKekId());
            if (StringUtils.isBlank(password)) {
                return null;
            }
        }
        String workKeyPlaintext = null;
        try {
            switch (AlgorithmType.getByType(keyOrdersAddVO.getAlgorithm().toLowerCase(Locale.ENGLISH))) {
                case aes:
                    AESKeyGenParams aesKeyGenParams = new AESKeyGenParams();
                    aesKeyGenParams.setKeySize(Integer.valueOf(keyOrdersAddVO.getBitLength()));
                    aesKeyGenParams.setPassword(password);
                    KeyUtil.genKey(aesKeyGenParams);
                    workKeyPlaintext = isBase64 ? aesKeyGenParams.getKeyBase64() : aesKeyGenParams.getKeyHex();
                    break;
                case desede:
                    DES3KeyGenParams des3KeyGenParams = new DES3KeyGenParams();
                    des3KeyGenParams.setKeySize(Integer.valueOf(keyOrdersAddVO.getBitLength()));
                    des3KeyGenParams.setPassword(password);
                    KeyUtil.genKey(des3KeyGenParams);
                    workKeyPlaintext = isBase64 ? des3KeyGenParams.getKeyBase64() : des3KeyGenParams.getKeyHex();
                    break;
                case sm4:
                    SM4KeyGenParams sm4KeyGenParams = new SM4KeyGenParams();
                    sm4KeyGenParams.setPassword(password);
                    KeyUtil.genKey(sm4KeyGenParams);
                    workKeyPlaintext = isBase64 ? sm4KeyGenParams.getKeyBase64() : sm4KeyGenParams.getKeyHex();
                    break;
                default:
            }
        } catch (Exception e) {
            log.error("doSymmetricOrder 创建密钥失败 ");
        }
        return workKeyPlaintext;
    }

    /**
     * 进行非对称密钥业务
     *
     * @param keyOrdersBean 密钥订单
     */
    private AsymmetricSecretVO doAsymmetricOrder(KeyOrdersBean keyOrdersBean) {
        log.info("doAsymmetricOrder,{}", keyOrdersBean);
//                非对称密钥
//                进行容器、密钥、容器-密钥关系生成
//                进行密钥订单更新

        //进行参数校验,在进行订单保存时已经校验了，因此此处无需进行校验
        ObjectMapper objectMapper = new ObjectMapper();
        KeyOrdersAddVO keyOrdersAddVO;
        try {
            keyOrdersAddVO = objectMapper.readValue(keyOrdersBean.getMeta(), KeyOrdersAddVO.class);
        } catch (IOException e) {
            log.error("doSymmetricOrder 转换数据错误");
//            throw new ValidationException("非对称密钥新增转换数据错误");
            keyOrdersBean.setErrorReason("非对称密钥新增转换数据错误");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        // 进行参数赋值
        // 进行数据库新增及调用软硬件进行密钥生成
        //1.生成三级密钥
        Map<String, String> keyMap = this.getAsymmetricPlaintext(keyOrdersAddVO);
        String priKeyPlaintext = keyMap.get("priKeyPlaintext"), pubKeyPlaintext = keyMap.get("pubKeyPlaintext");

        if (StringUtils.isBlank(priKeyPlaintext) || StringUtils.isBlank(pubKeyPlaintext)) {
            log.error("doAsymmetricOrder 创建密钥失败 ");
            keyOrdersBean.setErrorReason("创建密钥失败");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        //2用二级密钥加密生成的明文密钥
        CipherTextVo priKeyCipherTextVo = keksService.getEncryptString(priKeyPlaintext, keyOrdersBean.getCreatorId());
        if (priKeyCipherTextVo == null) {
            log.error("doAsymmetricOrder 密钥信息加密失败 ");
            keyOrdersBean.setErrorReason("密钥信息加密失败");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }
        CipherTextVo pubKeyCipherTextVo = keksService.getEncryptString(pubKeyPlaintext, keyOrdersBean.getCreatorId());
        if (pubKeyCipherTextVo == null) {
            log.error("doAsymmetricOrder 密钥信息加密失败 ");
            keyOrdersBean.setErrorReason("密钥信息加密失败");
            keyOrdersRepository.save(keyOrdersBean);
            return null;
        }

        //3进行信息存储，
        //3.1将密钥表进行存储，
        SecretsBean privateKeyBean = this.saveSecretsBean(keyOrdersAddVO, priKeyCipherTextVo.getKekId(), keyMap.get("priKeyFormat"), SecretsBean.NOTE_PRIVATE_KEY, keyOrdersBean.getCreatorId());
        SecretsBean publicKeyBean = this.saveSecretsBean(keyOrdersAddVO, pubKeyCipherTextVo.getKekId(), keyMap.get("pubKeyFormat"), SecretsBean.NOTE_PUBLIC_KEY, keyOrdersBean.getCreatorId());
        //3.2将加密内容存储至密钥存储表，
        secretsStoreService.saveSecretsStoreBean(privateKeyBean, priKeyCipherTextVo.getCipherText());
        secretsStoreService.saveSecretsStoreBean(publicKeyBean, pubKeyCipherTextVo.getCipherText());
        //3.3将容器表、关联关系表存储
        ContainersBean containersBean = containersService.saveContainersBean(keyOrdersAddVO.getName(), keyOrdersBean.getCreatorId());
        containerSecretService.saveContainerSecrets(containersBean.getUuid(), keyOrdersAddVO.getName(), privateKeyBean.getUuid(), publicKeyBean.getUuid());
        //3.4进行密钥订单的更新
        keyOrdersBean.setContainerId(containersBean.getUuid());
        keyOrdersBean.setStatus(KeyOrderStatus.Success.name());
        keyOrdersBean.setUpdatedTime(privateKeyBean.getCreatedTime());
        keyOrdersRepository.save(keyOrdersBean);

        AsymmetricSecretVO secretVO = new AsymmetricSecretVO();
        secretVO.setPrivateKeyBean(privateKeyBean);
        secretVO.setPublicKeyBean(publicKeyBean);
        secretVO.setContainersBean(containersBean);

        return secretVO;
    }


    /**
     * 获取非对称加密密钥信息
     *
     * @param keyOrdersAddVO 密钥订单基础信息
     * @return 非对称加密密钥信息MAP, 包含：priKeyPlaintext私钥明文信息，pubKeyPlaintext公钥明文信息，priKeyFormat私钥密钥格式，pubKeyFormat公钥密钥格式
     */
    private Map<String, String> getAsymmetricPlaintext(KeyOrdersAddVO keyOrdersAddVO) {
        Map<String, String> returnMap = new HashMap<>(4);
        //返回私钥明文信息初始化
        returnMap.put("priKeyPlaintext", null);
        //返回公钥明文信息初始化
        returnMap.put("pubKeyPlaintext", null);
        //如果有password，则需要进行解密后再赋值生成密钥
        String password = null;
        if (StringUtils.isNotBlank(keyOrdersAddVO.getPassword()) && StringUtils.isNotBlank(keyOrdersAddVO.getKekId())) {
            password = keksService.getDecryptString(keyOrdersAddVO.getPassword(), keyOrdersAddVO.getKekId());
            if (StringUtils.isBlank(password)) {
                return returnMap;
            }
        }
        boolean isPkcs8 = AsymmetricCommonPrivateKeyFormatType.getByType(keyOrdersAddVO.getKeyFormat()).equals(AsymmetricCommonPrivateKeyFormatType.Pkcs8);

        try {
            switch (AlgorithmType.getByType(keyOrdersAddVO.getAlgorithm().toLowerCase(Locale.ENGLISH))) {
                case rsa:
                    RSAKeyGenParams rsaKeyGenParams = new RSAKeyGenParams();
                    rsaKeyGenParams.setKeySize(Integer.valueOf(keyOrdersAddVO.getBitLength()));
                    rsaKeyGenParams.setPassword(password);
                    KeyUtil.genKey(rsaKeyGenParams);
                    if (isPkcs8) {
                        returnMap.put("priKeyPlaintext", rsaKeyGenParams.getPriKeyPKCS8Pem());
                        returnMap.put("pubKeyPlaintext", rsaKeyGenParams.getPubKeyX509Pem());
                        returnMap.put("priKeyFormat", AsymmetricCommonPrivateKeyFormatType.Pkcs8.name());
                        returnMap.put("pubKeyFormat", AsymmetricPublicKeyFormatType.X509.name());
                    } else {
                        returnMap.put("priKeyPlaintext", rsaKeyGenParams.getPriKeyPKCS1Pem());
                        returnMap.put("pubKeyPlaintext", rsaKeyGenParams.getPubKeyPKCS1Pem());
                        returnMap.put("priKeyFormat", AsymmetricCommonPrivateKeyFormatType.Pkcs1.name());
                        returnMap.put("pubKeyFormat", AsymmetricPublicKeyFormatType.Pkcs1.name());
                    }
                    break;
                case dsa:
                    DSAKeyGenParams dsaKeyGenParams = new DSAKeyGenParams();
                    dsaKeyGenParams.setKeySize(Integer.valueOf(keyOrdersAddVO.getBitLength()));
                    dsaKeyGenParams.setPassword(password);
                    KeyUtil.genKey(dsaKeyGenParams);
                    returnMap.put("pubKeyPlaintext", dsaKeyGenParams.getPubKeyX509Pem());
                    returnMap.put("pubKeyFormat", AsymmetricPublicKeyFormatType.X509.name());
                    if (isPkcs8) {
                        returnMap.put("priKeyPlaintext", dsaKeyGenParams.getPriKeyPKCS8Pem());
                        returnMap.put("priKeyFormat", AsymmetricCommonPrivateKeyFormatType.Pkcs8.name());
                    } else {
                        returnMap.put("priKeyPlaintext", dsaKeyGenParams.getPriKeyPKCS1Pem());
                        returnMap.put("priKeyFormat", AsymmetricCommonPrivateKeyFormatType.Pkcs1.name());
                    }
                    break;
                case sm2:
                    SM2KeyGenParams sm2KeyGenParams = new SM2KeyGenParams();
                    sm2KeyGenParams.setPassword(password);
                    KeyUtil.genKey(sm2KeyGenParams);
                    returnMap.put("pubKeyPlaintext", sm2KeyGenParams.getPubKeyX509Pem());
                    returnMap.put("pubKeyFormat", AsymmetricPublicKeyFormatType.X509.name());
                    if (isPkcs8) {
                        returnMap.put("priKeyPlaintext", sm2KeyGenParams.getPriKeyPKCS8Pem());
                        returnMap.put("priKeyFormat", AsymmetricCommonPrivateKeyFormatType.Pkcs8.name());
                    } else {
                        returnMap.put("priKeyPlaintext", sm2KeyGenParams.getPriKeyGMTPem());
                        returnMap.put("priKeyFormat", AsymmetricSM2PrivateKeyFormatType.GMT.name());
                    }

                    break;
                default:
            }
        } catch (Exception e) {
            log.error("doAsymmetricOrder 创建密钥失败 ", e);
        }
        return returnMap;
    }

    /**
     * 密钥分页查询
     *
     * @param pageRequestDate 分页、排序对象
     * @param searchParams    查询条件
     * @return 返回结果集
     */
    @Override
    public Page searchSecrets(PageRequestDate pageRequestDate, SecretsBean searchParams) {

        SysUserBean loginUser = sysUserService.findLoginSysUser();
        if (loginUser == null) {
            throw new UserInfoInVaildException();
        }
        //进行分页设置
        return secretsRepository.findAll((Specification<SecretsBean>) (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.equal(root.get("creatorId").as(String.class), loginUser.getUuid()));
            list.add(cb.equal(root.get("deleted").as(Boolean.class), false));
            //TODO 查询条件
            if (StringUtils.isNotBlank(searchParams.getName())) {
                list.add(cb.like(root.get("name").as(String.class), "%" + searchParams.getName().trim() + "%"));
            }
            if (StringUtils.isNotBlank(searchParams.getAlgorithm())) {
                list.add(cb.like(root.get("algorithm").as(String.class), "%" + searchParams.getAlgorithm().trim() + "%"));
            }
            if (StringUtils.isNotBlank(searchParams.getMode())) {
                list.add(cb.like(root.get("mode").as(String.class), "%" + searchParams.getMode().trim() + "%"));
            }
            if (StringUtils.isNotBlank(searchParams.getNote())) {
                list.add(cb.like(root.get("note").as(String.class), "%" + searchParams.getNote().trim() + "%"));
            }
            if (StringUtils.isNotBlank(searchParams.getBitLength())) {
                list.add(cb.equal(root.get("bitLength").as(String.class), searchParams.getBitLength().trim()));
            }
            if (StringUtils.isNotBlank(searchParams.getSecretType())) {
                list.add(cb.equal(root.get("secretType").as(String.class), searchParams.getSecretType().trim()));
            }
            if (StringUtils.isNotEmpty(searchParams.getCreatedTimeBegin())) {
                list.add(cb.greaterThanOrEqualTo(root.get("createdTime").as(String.class), searchParams.getCreatedTimeBegin().trim()));
            }
            if (StringUtils.isNotEmpty(searchParams.getCreatedTimeEnd())) {
                list.add(cb.lessThanOrEqualTo(root.get("createdTime").as(String.class), searchParams.getCreatedTimeEnd().trim()));
            }
//            if (StringUtils.isNotBlank(searchParams.getExpiration())) {
//                list.add(cb.equal(root.get("expiration").as(String.class),searchParams.getExpiration().trim()));
//            }

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        }, pageRequestDate.getPageRequest());
    }

    /**
     * 密钥信息单个查询
     *
     * @param uuid 密钥主键
     * @return 密钥信息
     */
    @Override
    public SecretsBean searchSecret(String uuid) throws NotFoundException, MissingServletRequestParameterException {
        return checkPermission(uuid);
    }

    /**
     * 密钥删除，假删除
     *
     * @param uuid 密钥主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSecret(String uuid) throws NotFoundException, MissingServletRequestParameterException {
        SecretsBean bean = this.checkPermission(uuid);
        SecretsStoreBean secretsStoreBean = secretsStoreRepository.findBySecretId(uuid);
        if (secretsStoreBean == null) {
            throw new NotFoundException("密钥存储对象不存在");
        }
        bean.setDeleted(true);
        secretsStoreBean.setDeleted(true);
        secretsRepository.save(bean);
        secretsStoreRepository.save(secretsStoreBean);
        containerSecretService.deleteBySecretUuid(uuid);
    }

    /**
     * 密钥下载
     *
     * @param uuid 密钥主键
     */
    @Override
    public String downloadSecret(String uuid) throws NotFoundException, MissingServletRequestParameterException {
        SecretsBean bean = this.checkPermission(uuid);
        SecretsStoreBean secretsStoreBean = secretsStoreRepository.findBySecretId(uuid);
        if (secretsStoreBean == null) {
            throw new NotFoundException("密钥存储对象不存在");
        }
        //获取用户二级密钥对三级密钥进行解密
        return keksService.getDecryptString(secretsStoreBean.getCypherText(), bean.getKekId());
    }

    /**
     * 进行密钥表存储
     *
     * @param keyOrdersAddVO 密钥订单参数对象
     * @param kekId          二级密钥id
     * @param keyFormat      密钥格式，非对称加密公私钥需要传
     * @param userId         操作用户
     * @return 密钥存储后对象
     */
    private SecretsBean saveSecretsBean(KeyOrdersAddVO keyOrdersAddVO, String kekId, String keyFormat, String note, String userId) {
        String nowTime = DateUtil.getNowDate();
        SecretsBean secretsBean = new SecretsBean();
        BeanUtils.copyProperties(keyOrdersAddVO, secretsBean);
        secretsBean.setDeleted(false);
        secretsBean.setCreatedTime(nowTime);
        secretsBean.setSecretType(keyOrdersAddVO.getType());
        secretsBean.setCreatorId(userId);
        secretsBean.setKeyFormat(keyFormat);
        secretsBean.setOutputFormat(keyOrdersAddVO.getOutputFormat());
        secretsBean.setKekId(kekId);
        secretsBean.setStatus(SecretKeyStatus.Normal.name());
        secretsBean.setNote(note);
        return secretsRepository.save(secretsBean);
    }

    /**
     * 校验登录用户是否有数据的操作权限
     *
     * @param uuid 数据id
     * @return 数据对象
     * @throws MissingServletRequestParameterException 异常信息-主键参数必填
     * @throws NotFoundException                       异常信息-未找到对象
     */
    private SecretsBean checkPermission(String uuid) throws MissingServletRequestParameterException, NotFoundException {
        if (StringUtils.isBlank(uuid)) {
            throw new MissingServletRequestParameterException("主键字段uuid", "String");
        }
        SysUserBean loginUser = sysUserService.findLoginSysUser();
        if (loginUser == null) {
            throw new UserInfoInVaildException();
        }
        Optional<SecretsBean> optional = secretsRepository.findById(uuid);
        //校验是否存在，如果不存在，直接返回成功
        if (!optional.isPresent()) {
            throw new NotFoundException("密钥对象不存在");
        }
        SecretsBean bean = optional.get();
        //被删除
        if (bean.getDeleted() || !loginUser.getUuid().equalsIgnoreCase(bean.getCreatorId())) {
            throw new NotFoundException("密钥对象不存在");
        }
        return bean;
    }

    /**
     * 进行密钥上传（新增）
     *
     * @param secretsAddVO 密钥数据
     * @return 新增数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SecretsBean uploadSecrets(SecretsAddVO secretsAddVO) {
        //参数校验
        SysUserBean loginUser = sysUserService.findLoginSysUser();
        if (loginUser == null) {
            throw new UserInfoInVaildException();
        }
        this.checkInput(secretsAddVO, loginUser.getUuid());
        //进行新增
        //用用户的二级密钥对传入密码进行加密
        if (StringUtils.isNotBlank(secretsAddVO.getPassword())) {
            //CipherTextVo getEncryptString(String plainText, String creatorId);
            CipherTextVo cipherTextVo = keksService.getEncryptString(secretsAddVO.getPassword(), loginUser.getUuid());
            if (cipherTextVo == null) {
                throw new RequestRejectedException("二级密钥加密传入密码错误");
            }
            secretsAddVO.setPassword(cipherTextVo.getCipherText());
            secretsAddVO.setKekId(cipherTextVo.getKekId());
        }
        //进行参数赋值
        KeyOrdersAddVO keyOrdersAddVO = new KeyOrdersAddVO();
        BeanUtils.copyProperties(secretsAddVO, keyOrdersAddVO);
        keyOrdersAddVO.setType(secretsAddVO.getSecretType());
        //进行数据库新增及调用软硬件进行密钥生成
        //1.生成三级密钥
        //2用二级密钥加密生成的明文密钥
        CipherTextVo cipherTextVo = keksService.getEncryptString(secretsAddVO.getPayload(), loginUser.getUuid());
        if (cipherTextVo == null) {
            log.error("doSymmetricSecret 密钥信息加密失败 ");
            return null;
        }
        //3进行信息存储
        //3.1将密钥表进行存储
        SecretsBean secretsBean = this.saveSecretsBean(keyOrdersAddVO, cipherTextVo.getKekId(), secretsAddVO.getKeyFormat(), secretsAddVO.getNote(), loginUser.getUuid());
        //3.2将加密内容存储至密钥存储表
        secretsStoreService.saveSecretsStoreBean(secretsBean, cipherTextVo.getCipherText());
        return secretsBean;
    }


    /**
     * 进行密钥上传数据校验，不合规会抛出ValidationException异常
     *
     * @param secretsBean   密钥上传数据
     * @param loginUserUuid 操作用户，用来校验当前用户下是否已存在相同名称的密钥
     */
    private void checkInput(SecretsBean secretsBean, String loginUserUuid) {
        if (!RegExpUtil.checkSecretOrderAlgorithm(secretsBean.getSecretType(), secretsBean.getAlgorithm(), secretsBean.getBitLength())) {
            throw new ValidationException("传入密钥算法不规范，校验失败");
        }
        if (!RegExpUtil.checkKeyExpiry(secretsBean.getExpiration())) {
            throw new ValidationException("传入密钥有效期不规范，请传入比当前日期大的日期，格式为'yyyy-MM-dd'");
        }
        //密码长度校验去除，上传忽略密码校验
        //进行密钥格式、输出格式校验
        //如果是对称加密，输出格式只能为hex/base64,密钥格式为空
        //如果是非对称加密，密钥格式为pkcs8/pkcs1、输出格式为空，如果传入密钥格式为pkcs1，则不能输入密码
        boolean isPubKey = false, isPriKey = false;
        switch (AlgorithmType.getByType(secretsBean.getAlgorithm())) {
            case aes:
            case desede:
            case sm4:
                if (StringUtils.isBlank(secretsBean.getOutputFormat()) ||
                        DataOutputType.getByType(secretsBean.getOutputFormat()).equals(DataOutputType.Other)
                ) {
                    throw new ValidationException("传入输出格式不规范，校验失败");
                }
                //密码长度校验
                //唯一性校验
                //查询当前登录用户名下是否有相同名称的密钥
                long totalNumber = secretsRepository.countByNameAndDeletedAndCreatorIdOrderByCreatedTimeDesc(secretsBean.getName().trim(),false, loginUserUuid);
                if (totalNumber > 0) {
                    throw new ValidationException("传入密钥名称已存在");
                }
                secretsBean.setNote(null);
                secretsBean.setPassword(null);
                secretsBean.setKeyFormat(null);
                break;
            case rsa:
            case dsa:
                if (StringUtils.isBlank(secretsBean.getKeyFormat()) ||
                        AsymmetricCommonPrivateKeyFormatType.getByType(secretsBean.getKeyFormat()).equals(AsymmetricCommonPrivateKeyFormatType.Other)
                ) {
                    throw new ValidationException("传入密钥格式不规范，校验失败");
                    //密码长度校验
                } else if (!SecretsBean.NOTE_PRIVATE_KEY.equalsIgnoreCase(secretsBean.getNote()) && !SecretsBean.NOTE_PUBLIC_KEY.equalsIgnoreCase(secretsBean.getNote())) {
                    throw new ValidationException(String.format("非对称密钥需要传入正确的备注字段note，可选[%s,%s]", SecretsBean.NOTE_PRIVATE_KEY, SecretsBean.NOTE_PUBLIC_KEY));
                }
                isPubKey = SecretsBean.NOTE_PUBLIC_KEY.equalsIgnoreCase(secretsBean.getNote());
                isPriKey = !isPubKey;
                secretsBean.setOutputFormat(null);
                break;
            case sm2:
                if (StringUtils.isBlank(secretsBean.getKeyFormat()) ||
                        AsymmetricSM2PrivateKeyFormatType.getByType(secretsBean.getKeyFormat()).equals(AsymmetricSM2PrivateKeyFormatType.Other)
                ) {
                    throw new ValidationException("传入密钥格式不规范，校验失败");
                } else if (!SecretsBean.NOTE_PRIVATE_KEY.equalsIgnoreCase(secretsBean.getNote()) && !SecretsBean.NOTE_PUBLIC_KEY.equalsIgnoreCase(secretsBean.getNote())) {
                    throw new ValidationException(String.format("非对称密钥需要传入正确的备注字段note，可选[%s,%s]", SecretsBean.NOTE_PRIVATE_KEY, SecretsBean.NOTE_PUBLIC_KEY));
                }
                isPubKey = SecretsBean.NOTE_PUBLIC_KEY.equalsIgnoreCase(secretsBean.getNote());
                isPriKey = !isPubKey;
                secretsBean.setOutputFormat(null);
                break;
            default:
        }
        if (isPubKey || isPriKey) {
            //查询当前登录用户名下是否有相同名称的密钥
            long totalNumber = secretsRepository.countByNameAndDeletedAndNoteAndCreatorIdOrderByCreatedTimeDesc(secretsBean.getName().trim(),false, secretsBean.getNote(), loginUserUuid);
            if (totalNumber > 0) {
                throw new ValidationException("传入密钥名称已存在");
            }
        }

    }
}
